Main Page   Modules   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

tinyxml.h

Go to the documentation of this file.
00001 /*
00002 www.sourceforge.net/projects/tinyxml
00003 Original code (2.0 and earlier )copyright (c) 2000-2002 Lee Thomason (www.grinninglizard.com)
00004 
00005 This software is provided 'as-is', without any express or implied
00006 warranty. In no event will the authors be held liable for any
00007 damages arising from the use of this software.
00008 
00009 Permission is granted to anyone to use this software for any
00010 purpose, including commercial applications, and to alter it and
00011 redistribute it freely, subject to the following restrictions:
00012 
00013 1. The origin of this software must not be misrepresented; you must
00014 not claim that you wrote the original software. If you use this
00015 software in a product, an acknowledgment in the product documentation
00016 would be appreciated but is not required.
00017 
00018 2. Altered source versions must be plainly marked as such, and
00019 must not be misrepresented as being the original software.
00020 
00021 3. This notice may not be removed or altered from any source
00022 distribution.
00023 */
00024 
00025 /*
00026 In accordance with item 2 of the above license,
00027 this file has been modified from the original version,
00028 to provide a minimal pull-parse back-end that cuts
00029 down on the memory footprint when doing read-only operations.
00030 */
00031 
00032 
00033 #ifndef TINYXML_INCLUDED
00034 #define TINYXML_INCLUDED
00035 
00036 #ifdef _MSC_VER
00037 #pragma warning( disable : 4530 )
00038 #pragma warning( disable : 4786 )
00039 #endif
00040 
00041 #include <cctype>
00042 #include <cstdio>
00043 #include <cstdlib>
00044 #include <cstring>
00045 #include <cassert>
00046 #include <deque>
00047 
00048 // Help out windows:
00049 #if defined( _DEBUG ) && !defined( DEBUG )
00050 #define DEBUG
00051 #endif
00052 
00053 #if defined( DEBUG ) && defined( _MSC_VER )
00054 #include <windows.h>
00055 #define TIXML_LOG OutputDebugString
00056 #else
00057 #define TIXML_LOG printf
00058 #endif
00059 
00060 #ifdef TIXML_USE_STL
00061     #include <string>
00062     #include <iostream>
00063     //#include <ostream>
00064     #define TIXML_STRING    std::string
00065     #define TIXML_ISTREAM   std::istream
00066     #define TIXML_OSTREAM   std::ostream
00067 #else
00068     #include "tinystr.h"
00069     #define TIXML_STRING    TiXmlString
00070     #define TIXML_OSTREAM   TiXmlOutStream
00071 #endif
00072 
00073 class TiPullXmlDocument;
00074 class TiPullXmlElement;
00075 class TiPullXmlComment;
00076 class TiPullXmlUnknown;
00077 class TiPullXmlAttribute;
00078 class TiPullXmlText;
00079 class TiPullXmlDeclaration;
00080 
00081 class TiPullXmlParsingData;
00082 
00083 /*  Internal structure for tracking location of items 
00084     in the XML file.
00085 */
00086 struct TiPullXmlCursor
00087 {
00088     TiPullXmlCursor()       { Clear(); }
00089     TiPullXmlCursor(int pos) : filepos(pos) { }
00090     void Clear()        { filepos = -1; }
00091     bool operator==(const TiPullXmlCursor& ref) const
00092     { return (filepos == ref.filepos); }
00093 
00094     int filepos;
00095 };
00096 
00097 
00098 // Only used by Attribute::Query functions
00099 enum 
00100 { 
00101     TIXML_SUCCESS,
00102     TIXML_NO_ATTRIBUTE,
00103     TIXML_WRONG_TYPE
00104 };
00105 
00106 /** TiXmlBase is a base class for every class in TinyXml.
00107     It does little except to establish that TinyXml classes
00108     can be printed and provide some utility functions.
00109 
00110     In XML, the document and elements can contain
00111     other elements and other types of nodes.
00112 
00113     @verbatim
00114     A Document can contain: Element (container or leaf)
00115                             Comment (leaf)
00116                             Unknown (leaf)
00117                             Declaration( leaf )
00118 
00119     An Element can contain: Element (container or leaf)
00120                             Text    (leaf)
00121                             Attributes (not on tree)
00122                             Comment (leaf)
00123                             Unknown (leaf)
00124 
00125     A Decleration contains: Attributes (not on tree)
00126     @endverbatim
00127 */
00128 class TiPullXmlBase
00129 {
00130     friend class TiPullXmlNode;
00131     friend class TiPullXmlElement;
00132     friend class TiPullXmlDocument;
00133 
00134 public:
00135     TiPullXmlBase()                             {}
00136     virtual ~TiPullXmlBase()                    {}
00137 
00138     struct ParsePosition
00139     {
00140         ParsePosition() : data(0), pos(0) { }
00141         ParsePosition(const char* data_, int pos_) : data(data_), pos(pos_) { }
00142         const char* data;
00143         TiPullXmlCursor pos;
00144     };
00145 
00146     /** All TinyXml classes can print themselves to a filestream.
00147         This is a formatted print, and will insert tabs and newlines.
00148         
00149         (For an unformatted stream, use the << operator.)
00150     */
00151     virtual void Print( FILE* cfile, int depth ) const = 0;
00152 
00153     /** The world does not agree on whether white space should be kept or
00154         not. In order to make everyone happy, these global, static functions
00155         are provided to set whether or not TinyXml will condense all white space
00156         into a single space or not. The default is to condense. Note changing this
00157         values is not thread safe.
00158     */
00159     static void SetCondenseWhiteSpace( bool condense )      { condenseWhiteSpace = condense; }
00160 
00161     /// Return the current white space setting.
00162     static bool IsWhiteSpaceCondensed()                     { return condenseWhiteSpace; }
00163 
00164 protected:
00165     // See STL_STRING_BUG
00166     // Utility class to overcome a bug.
00167     class StringToBuffer
00168     {
00169       public:
00170         StringToBuffer( const TIXML_STRING& str );
00171         ~StringToBuffer();
00172         char* buffer;
00173     };
00174 
00175     inline static bool  IsWhiteSpace( int c )       { return ( isspace( c ) || c == '\n' || c == '\r' ); }
00176 
00177     virtual void StreamOut (TIXML_OSTREAM *) const = 0;
00178 
00179     #ifdef TIXML_USE_STL
00180         static bool StreamWhiteSpace( TIXML_ISTREAM * in, TIXML_STRING * tag );
00181         static bool StreamTo( TIXML_ISTREAM * in, int character, TIXML_STRING * tag );
00182     #endif
00183 
00184     /*  Reads an XML name into the string provided. Returns
00185         a pointer just past the last character of the name,
00186         or 0 if the function has an error.
00187     */
00188     static const char* ReadName( const char* p, TIXML_STRING* name );
00189 
00190     /*  Reads text. Returns a pointer past the given end tag.
00191         Wickedly complex options, but it keeps the (sensitive) code in one place.
00192     */
00193     static const char* ReadText(    const char* in,             // where to start
00194                                     TIXML_STRING* text,         // the string read
00195                                     bool ignoreWhiteSpace,      // whether to keep the white space
00196                                     const char* endTag,         // what ends this text
00197                                     bool ignoreCase );          // whether to ignore case in the end tag
00198 
00199     virtual bool Parse( ParsePosition in, const char* &out, bool throwaway ) = 0;
00200 
00201     // If an entity has been found, transform it into a character.
00202     static const char* GetEntity( const char* in, char* value );
00203 
00204     // Get a character, while interpreting entities.
00205     inline static const char* GetChar( const char* p, char* _value )
00206     {
00207         assert( p );
00208         if ( *p == '&' )
00209         {
00210             return GetEntity( p, _value );
00211         }
00212         else
00213         {
00214             *_value = *p;
00215             return p+1;
00216         }
00217     }
00218 
00219     // Puts a string to a stream, expanding entities as it goes.
00220     // Note this should not contian the '<', '>', etc, or they will be transformed into entities!
00221     static void PutString( const TIXML_STRING& str, TIXML_OSTREAM* out );
00222 
00223     static void PutString( const TIXML_STRING& str, TIXML_STRING* out );
00224 
00225     // Return true if the next characters in the stream are any of the endTag sequences.
00226     static bool StringEqual(    const char* p,
00227                                 const char* endTag,
00228                                 bool ignoreCase );
00229 
00230 
00231     enum
00232     {
00233         TIXML_NO_ERROR = 0,
00234         TIXML_ERROR,
00235         TIXML_ERROR_OPENING_FILE,
00236         TIXML_ERROR_OUT_OF_MEMORY,
00237         TIXML_ERROR_PARSING_ELEMENT,
00238         TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME,
00239         TIXML_ERROR_READING_ELEMENT_VALUE,
00240         TIXML_ERROR_READING_ATTRIBUTES,
00241         TIXML_ERROR_PARSING_EMPTY,
00242         TIXML_ERROR_READING_END_TAG,
00243         TIXML_ERROR_PARSING_UNKNOWN,
00244         TIXML_ERROR_PARSING_COMMENT,
00245         TIXML_ERROR_PARSING_DECLARATION,
00246         TIXML_ERROR_DOCUMENT_EMPTY,
00247 
00248         TIXML_ERROR_STRING_COUNT
00249     };
00250     static const char* errorString[ TIXML_ERROR_STRING_COUNT ];
00251 
00252     TiPullXmlCursor startPos;
00253 
00254 private:
00255     struct Entity
00256     {
00257         const char*     str;
00258         unsigned int    strLength;
00259         char            chr;
00260     };
00261     enum
00262     {
00263         NUM_ENTITY = 5,
00264         MAX_ENTITY_LENGTH = 6
00265 
00266     };
00267     static Entity entity[ NUM_ENTITY ];
00268     static bool condenseWhiteSpace;
00269 };
00270 
00271 
00272 /** The parent class for everything in the Document Object Model.
00273     (Except for attributes).
00274     Nodes have siblings, a parent, and children. A node can be
00275     in a document, or stand on its own. The type of a TiXmlNode
00276     can be queried, and it can be cast to its more defined type.
00277 */
00278 class TiPullXmlNode : public TiPullXmlBase
00279 {
00280     friend class TiPullXmlDocument;
00281     friend class TiPullXmlElement;
00282 
00283 public:
00284     #ifdef TIXML_USE_STL    
00285 
00286         /** An input stream operator, for every class. Tolerant of newlines and
00287             formatting, but doesn't expect them.
00288         */
00289         friend std::istream& operator >> (std::istream& in, TiPullXmlNode& base);
00290 
00291         /** An output stream operator, for every class. Note that this outputs
00292             without any newlines or formatting, as opposed to Print(), which
00293             includes tabs and new lines.
00294 
00295             The operator<< and operator>> are not completely symmetric. Writing
00296             a node to a stream is very well defined. You'll get a nice stream
00297             of output, without any extra whitespace or newlines.
00298             
00299             But reading is not as well defined. (As it always is.) If you create
00300             a TiXmlElement (for example) and read that from an input stream,
00301             the text needs to define an element or junk will result. This is
00302             true of all input streams, but it's worth keeping in mind.
00303 
00304             A TiXmlDocument will read nodes until it reads a root element, and
00305             all the children of that root element.
00306         */  
00307         friend std::ostream& operator<< (std::ostream& out, const TiPullXmlNode& base);
00308 
00309         /// Appends the XML node or attribute to a std::string.
00310         friend std::string& operator<< (std::string& out, const TiPullXmlNode& base );
00311 
00312     #else
00313         // Used internally, not part of the public API.
00314         friend TIXML_OSTREAM& operator<< (TIXML_OSTREAM& out, const TiPullXmlNode& base);
00315     #endif
00316 
00317     /** The types of XML nodes supported by TinyXml. (All the
00318             unsupported types are picked up by UNKNOWN.)
00319     */
00320     enum NodeType
00321     {
00322         DOCUMENT,
00323         ELEMENT,
00324         COMMENT,
00325         UNKNOWN,
00326         TEXT,
00327         DECLARATION,
00328         TYPECOUNT
00329     };
00330 
00331     virtual ~TiPullXmlNode();
00332 
00333     /** The meaning of 'value' changes for the specific type of
00334         TiPullXmlNode.
00335         @verbatim
00336         Document:   filename of the xml file
00337         Element:    name of the element
00338         Comment:    the comment text
00339         Unknown:    the tag contents
00340         Text:       the text string
00341         @endverbatim
00342 
00343         The subclasses will wrap this function.
00344     */
00345     const char * Value() const { return value.c_str (); }
00346 
00347     void SetValue(const char* val) {}
00348     #ifdef TIXML_USE_STL
00349     void SetValue(const std::string& _value) {}
00350     #endif
00351 
00352     TiPullXmlNode* LinkActiveChild(TiPullXmlNode* node);
00353 
00354     /// One step up the DOM.
00355     TiPullXmlNode* Parent() const                   { return parent; }
00356 
00357     TiPullXmlNode* FirstChild( );           ///< The first child of this node with the matching 'value'. Will be null if none found.
00358 
00359     TiPullXmlNode* FirstChild( const char * value, NodeType _type );            ///< The first child of this node with the matching 'value'. Will be null if none found.
00360 
00361     #ifdef TIXML_USE_STL
00362     TiPullXmlNode* FirstChild( const std::string& _value, NodeType _type )
00363     {   return FirstChild (_value.c_str(), _type);  }   ///< STL std::string form.
00364     #endif
00365 
00366     TiPullXmlNode* NextSibling( ) ;
00367 
00368     /// Navigate to a sibling node with the given 'value'.
00369     TiPullXmlNode* NextSibling( const char * _value, NodeType _type ) ;
00370     
00371     #ifdef TIXML_USE_STL
00372     TiPullXmlNode* NextSibling( const std::string& _value, NodeType _type ) 
00373     {   return NextSibling (_value.c_str(), _type); }   ///< STL std::string form.
00374     #endif
00375 
00376     /** Convenience function to get through elements.
00377         Calls NextSibling and ToElement. Will skip all non-Element
00378         nodes. Returns 0 if there is not another element.
00379     */
00380     TiPullXmlElement* NextSiblingElement( ) ;
00381     TiPullXmlElement* NextSiblingElement( const char * _value ) 
00382     { TiPullXmlNode* n = NextSibling(_value, ELEMENT); return n ? n->ToElement() : 0; }
00383 
00384     #ifdef TIXML_USE_STL
00385     TiPullXmlElement* NextSiblingElement( const std::string& _value) 
00386     {   return NextSiblingElement (_value.c_str ());    }   ///< STL std::string form.
00387     #endif
00388 
00389     /// Convenience function to get through elements.
00390     TiPullXmlElement* FirstChildElement( ) ;
00391 
00392     /// Convenience function to get through elements.
00393     TiPullXmlElement* FirstChildElement( const char * _value ) 
00394     { TiPullXmlNode* n = FirstChild(_value, ELEMENT); return n ? n->ToElement() : 0; }
00395 
00396     #ifdef TIXML_USE_STL
00397     TiPullXmlElement* FirstChildElement( const std::string& _value ) const
00398     {   return FirstChildElement (_value.c_str ()); }   ///< STL std::string form.
00399     #endif
00400 
00401     /** Query the type (as an enumerated value, above) of this node.
00402         The possible types are: DOCUMENT, ELEMENT, COMMENT,
00403                                 UNKNOWN, TEXT, and DECLARATION.
00404     */
00405     virtual NodeType Type() const   { return type; }
00406 
00407     bool hasChildren() const { return (endPosOpen.filepos >= 0); }
00408 
00409     /** Return a pointer to the Document this node lives in.
00410         Returns null if not in a document.
00411     */
00412     TiPullXmlDocument* GetDocument() const;
00413 
00414     TiPullXmlDocument* ToDocument()const        { return ( this && type == DOCUMENT ) ? (TiPullXmlDocument*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
00415     TiPullXmlElement*  ToElement() const        { return ( this && type == ELEMENT  ) ? (TiPullXmlElement*)  this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
00416     TiPullXmlComment*  ToComment() const        { return ( this && type == COMMENT  ) ? (TiPullXmlComment*)  this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
00417     TiPullXmlUnknown*  ToUnknown() const        { return ( this && type == UNKNOWN  ) ? (TiPullXmlUnknown*)  this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
00418     TiPullXmlText*     ToText()     const       { return ( this && type == TEXT     ) ? (TiPullXmlText*)     this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
00419     TiPullXmlDeclaration* ToDeclaration()const  { return ( this && type == DECLARATION ) ? (TiPullXmlDeclaration*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
00420 
00421     /** Return the position, in the original source file, of this node or attribute.
00422         The row and column are 1-based. (That is the first row and first column is
00423         1,1). If the returns values are 0 or less, then the parser does not have
00424         a row and column value.
00425 
00426         Generally, the row and column value will be set when the TiXmlDocument::Load(),
00427         TiXmlDocument::LoadFile(), or any TiXmlNode::Parse() is called. It will NOT be set
00428         when the DOM was created from operator>>.
00429 
00430         The values reflect the initial load. Once the DOM is modified programmatically
00431         (by adding or changing nodes and attributes) the new values will NOT update to
00432         reflect changes in the document.
00433 
00434         There is a minor performance cost to computing the row and column. Computation
00435         can be disabled if TiXmlDocument::SetTabSize() is called with 0 as the value.
00436 
00437         @sa TiXmlDocument::SetTabSize()
00438     */
00439     int Row() const;
00440     int Column() const;
00441 
00442 protected:
00443     TiPullXmlNode( NodeType type );
00444 
00445     #ifdef TIXML_USE_STL
00446         // The real work of the input operator.
00447         virtual void StreamIn( TIXML_ISTREAM* in, TIXML_STRING* tag ) = 0;
00448     #endif
00449 
00450     // Figure out what is at *p, and parse it. Returns null if it is not an xml node.
00451     TiPullXmlNode* Identify( const char* start ) const;
00452 
00453     bool FindElementClose(ParsePosition in, const char* &out);
00454 
00455     // Internal Value function returning a TIXML_STRING
00456     TIXML_STRING SValue() const { return value ; }
00457 
00458     TiPullXmlNode*      parent;
00459     TiPullXmlNode*      activeChild;
00460     NodeType const      type;
00461 
00462     TiPullXmlCursor     endPosOpen;
00463     TiPullXmlCursor     endPosClose;
00464 
00465     TIXML_STRING        value;
00466 };
00467 
00468 
00469 /** An attribute is a name-value pair. Elements have an arbitrary
00470     number of attributes, each with a unique name.
00471 
00472     @note The attributes are not TiXmlNodes, since they are not
00473           part of the tinyXML document object model. There are other
00474           suggested ways to look at this problem.
00475 */
00476 class TiPullXmlAttribute : public TiPullXmlBase
00477 {
00478     friend class TiPullXmlAttributeSet;
00479 
00480 public:
00481     /// Construct an empty attribute.
00482     TiPullXmlAttribute()
00483     {
00484         document = 0;
00485         prev = next = 0;
00486     }
00487 
00488     #ifdef TIXML_USE_STL
00489     /// std::string constructor.
00490     TiPullXmlAttribute( const std::string& _name, const std::string& _value )
00491     {
00492         name = _name;
00493         value = _value;
00494         document = 0;
00495         prev = next = 0;
00496     }
00497     #endif
00498 
00499     /// Construct an attribute with a name and value.
00500     TiPullXmlAttribute( const char * _name, const char * _value )
00501     {
00502         name = _name;
00503         value = _value;
00504         document = 0;
00505         prev = next = 0;
00506     }
00507 
00508     const char*     Name()  const       { return name.c_str (); }       ///< Return the name of this attribute.
00509     const char*     Value() const       { return value.c_str (); }      ///< Return the value of this attribute.
00510     const int       IntValue() const;                                   ///< Return the value of this attribute, converted to an integer.
00511     const double    DoubleValue() const;                                ///< Return the value of this attribute, converted to a double.
00512 
00513     /** QueryIntValue examines the value string. It is an alternative to the
00514         IntValue() method with richer error checking.
00515         If the value is an integer, it is stored in 'value' and 
00516         the call returns TIXML_SUCCESS. If it is not
00517         an integer, it returns TIXML_WRONG_TYPE.
00518 
00519         A specialized but useful call. Note that for success it returns 0,
00520         which is the opposite of almost all other TinyXml calls.
00521     */
00522     int QueryIntValue( int* value ) const;
00523     /// QueryDoubleValue examines the value string. See QueryIntValue().
00524     int QueryDoubleValue( double* value ) const;
00525 
00526     void SetName( const char* _name )   { name = _name; }               ///< Set the name of this attribute.
00527     void SetValue( const char* _value ) { value = _value; }             ///< Set the value.
00528 
00529     void SetIntValue( int value );                                      ///< Set the value from an integer.
00530     void SetDoubleValue( double value );                                ///< Set the value from a double.
00531 
00532     #ifdef TIXML_USE_STL
00533     /// STL std::string form.
00534     void SetName( const std::string& _name )    
00535     {   
00536         StringToBuffer buf( _name );
00537         SetName ( buf.buffer ? buf.buffer : "error" );  
00538     }
00539     /// STL std::string form.   
00540     void SetValue( const std::string& _value )  
00541     {   
00542         StringToBuffer buf( _value );
00543         SetValue( buf.buffer ? buf.buffer : "error" );  
00544     }
00545     #endif
00546 
00547     /// Get the next sibling attribute in the DOM. Returns null at end.
00548     TiPullXmlAttribute* Next() const;
00549     /// Get the previous sibling attribute in the DOM. Returns null at beginning.
00550     TiPullXmlAttribute* Previous() const;
00551 
00552     bool operator==( const TiPullXmlAttribute& rhs ) const { return rhs.name == name; }
00553     bool operator<( const TiPullXmlAttribute& rhs )  const { return name < rhs.name; }
00554     bool operator>( const TiPullXmlAttribute& rhs )  const { return name > rhs.name; }
00555 
00556     /*  [internal use]
00557         Attribtue parsing starts: first letter of the name
00558                          returns: the next char after the value end quote
00559     */
00560     virtual bool Parse( ParsePosition in, const char* &out, bool throwaway );
00561 
00562     // [internal use]
00563     virtual void Print( FILE* cfile, int depth ) const;
00564 
00565     virtual void StreamOut( TIXML_OSTREAM * out ) const;
00566     // [internal use]
00567     // Set the document pointer so the attribute can report errors.
00568     void SetDocument( TiPullXmlDocument* doc )  { document = doc; }
00569 
00570 private:
00571     TiPullXmlDocument*  document;   // A pointer back to a document, for error reporting.
00572     TIXML_STRING name;
00573     TIXML_STRING value;
00574     TiPullXmlAttribute* prev;
00575     TiPullXmlAttribute* next;
00576 };
00577 
00578 
00579 /*  A class used to manage a group of attributes.
00580     It is only used internally, both by the ELEMENT and the DECLARATION.
00581     
00582     The set can be changed transparent to the Element and Declaration
00583     classes that use it, but NOT transparent to the Attribute
00584     which has to implement a next() and previous() method. Which makes
00585     it a bit problematic and prevents the use of STL.
00586 
00587     This version is implemented with circular lists because:
00588         - I like circular lists
00589         - it demonstrates some independence from the (typical) doubly linked list.
00590 */
00591 class TiPullXmlAttributeSet
00592 {
00593 public:
00594     TiPullXmlAttributeSet();
00595     ~TiPullXmlAttributeSet();
00596 
00597     void Add( TiPullXmlAttribute* attribute );
00598     void Remove( TiPullXmlAttribute* attribute );
00599 
00600     TiPullXmlAttribute* First() const   { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; }
00601     TiPullXmlAttribute* Last()  const   { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; }
00602     TiPullXmlAttribute* Find( const char * name ) const;
00603 
00604 private:
00605     TiPullXmlAttribute sentinel;
00606 };
00607 
00608 
00609 /** The element is a container class. It has a value, the element name,
00610     and can contain other elements, text, comments, and unknowns.
00611     Elements also contain an arbitrary number of attributes.
00612 */
00613 class TiPullXmlElement : public TiPullXmlNode
00614 {
00615 public:
00616     /// Construct an element.
00617     TiPullXmlElement (const char * in_value);
00618 
00619     #ifdef TIXML_USE_STL
00620     /// std::string constructor.
00621     TiPullXmlElement( const std::string& _value ) :     TiPullXmlNode( TiPullXmlNode::ELEMENT )
00622     {
00623         firstChild = lastChild = 0;
00624         value = _value;
00625     }
00626     #endif
00627 
00628     virtual ~TiPullXmlElement();
00629 
00630     /** Given an attribute name, Attribute() returns the value
00631         for the attribute of that name, or null if none exists.
00632     */
00633     const char* Attribute( const char* name ) const;
00634 
00635     /** Given an attribute name, Attribute() returns the value
00636         for the attribute of that name, or null if none exists.
00637         If the attribute exists and can be converted to an integer,
00638         the integer value will be put in the return 'i', if 'i'
00639         is non-null.
00640     */
00641     const char* Attribute( const char* name, int* i ) const;
00642 
00643     /** Given an attribute name, Attribute() returns the value
00644         for the attribute of that name, or null if none exists.
00645         If the attribute exists and can be converted to an double,
00646         the double value will be put in the return 'd', if 'd'
00647         is non-null.
00648     */
00649     const char* Attribute( const char* name, double* d ) const;
00650 
00651     /** QueryIntAttribute examines the attribute - it is an alternative to the
00652         Attribute() method with richer error checking.
00653         If the attribute is an integer, it is stored in 'value' and 
00654         the call returns TIXML_SUCCESS. If it is not
00655         an integer, it returns TIXML_WRONG_TYPE. If the attribute
00656         does not exist, then TIXML_NO_ATTRIBUTE is returned.
00657     */  
00658     int QueryIntAttribute( const char* name, int* value ) const;
00659     /// QueryDoubleAttribute examines the attribute - see QueryIntAttribute().
00660     int QueryDoubleAttribute( const char* name, double* value ) const;
00661 
00662     #ifdef TIXML_USE_STL
00663     const char* Attribute( const std::string& name ) const              { return Attribute( name.c_str() ); }
00664     const char* Attribute( const std::string& name, int* i ) const      { return Attribute( name.c_str(), i ); }
00665     #endif
00666 
00667     TiPullXmlAttribute* FirstAttribute() const  { return attributeSet.First(); }        ///< Access the first attribute in this element.
00668     TiPullXmlAttribute* LastAttribute() const   { return attributeSet.Last(); }     ///< Access the last attribute in this element.
00669 
00670     // [internal use]
00671 
00672     virtual void Print( FILE* cfile, int depth ) const;
00673 
00674 protected:
00675 
00676     // Used to be public [internal use]
00677     #ifdef TIXML_USE_STL
00678         virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
00679     #endif
00680     virtual void StreamOut( TIXML_OSTREAM * out ) const;
00681 
00682     /*  [internal use]
00683         Attribtue parsing starts: next char past '<'
00684                          returns: next char past '>'
00685     */
00686     virtual bool Parse( ParsePosition in, const char* &out, bool throwaway );
00687 
00688 private:
00689     TiPullXmlAttributeSet attributeSet;
00690 };
00691 
00692 
00693 /** An XML comment.
00694 */
00695 class TiPullXmlComment : public TiPullXmlNode
00696 {
00697 public:
00698     /// Constructs an empty comment.
00699     TiPullXmlComment() : TiPullXmlNode( TiPullXmlNode::COMMENT ) {}
00700     virtual ~TiPullXmlComment() {}
00701 
00702     // [internal use]
00703     virtual void Print( FILE* cfile, int depth ) const;
00704 protected:
00705     // used to be public
00706     #ifdef TIXML_USE_STL
00707         virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
00708     #endif
00709     virtual void StreamOut( TIXML_OSTREAM * out ) const;
00710     /*  [internal use]
00711         Attribtue parsing starts: at the ! of the !--
00712                          returns: next char past '>'
00713     */
00714     virtual bool Parse( ParsePosition in, const char* &out, bool throwaway );
00715 };
00716 
00717 
00718 /** XML text. Contained in an element.
00719 */
00720 class TiPullXmlText : public TiPullXmlNode
00721 {
00722     friend class TiPullXmlElement;
00723 public:
00724     TiPullXmlText( ) : TiPullXmlNode (TiPullXmlNode::TEXT)
00725     { }
00726     /// Constructor.
00727     TiPullXmlText (const char * initValue) : TiPullXmlNode (TiPullXmlNode::TEXT)
00728     { SetValue( initValue ); }
00729     virtual ~TiPullXmlText() {}
00730 
00731     #ifdef TIXML_USE_STL
00732     /// Constructor.
00733     TiPullXmlText( const std::string& initValue ) : TiPullXmlNode (TiPullXmlNode::TEXT)
00734     { SetValue( initValue ); }
00735     #endif
00736 
00737     // [internal use]
00738     virtual void Print( FILE* cfile, int depth ) const;
00739 
00740 protected :
00741     virtual void StreamOut ( TIXML_OSTREAM * out ) const;
00742     // [internal use]
00743     bool Blank() const; // returns true if all white space and new lines
00744     /*  [internal use]
00745             Attribtue parsing starts: First char of the text
00746                              returns: next char past '>'
00747     */
00748     virtual bool Parse( ParsePosition in, const char* &out, bool throwaway );
00749     // [internal use]
00750     #ifdef TIXML_USE_STL
00751         virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
00752     #endif
00753 };
00754 
00755 
00756 /** In correct XML the declaration is the first entry in the file.
00757     @verbatim
00758         <?xml version="1.0" standalone="yes"?>
00759     @endverbatim
00760 
00761     TinyXml will happily read or write files without a declaration,
00762     however. There are 3 possible attributes to the declaration:
00763     version, encoding, and standalone.
00764 
00765     Note: In this version of the code, the attributes are
00766     handled as special cases, not generic attributes, simply
00767     because there can only be at most 3 and they are always the same.
00768 */
00769 class TiPullXmlDeclaration : public TiPullXmlNode
00770 {
00771 public:
00772     /// Construct an empty declaration.
00773     TiPullXmlDeclaration()   : TiPullXmlNode( TiPullXmlNode::DECLARATION ) {}
00774 
00775 #ifdef TIXML_USE_STL
00776     /// Constructor.
00777     TiPullXmlDeclaration(   const std::string& _version,
00778                         const std::string& _encoding,
00779                         const std::string& _standalone )
00780             : TiPullXmlNode( TiPullXmlNode::DECLARATION )
00781     {
00782         version = _version;
00783         encoding = _encoding;
00784         standalone = _standalone;
00785     }
00786 #endif
00787 
00788     /// Construct.
00789     TiPullXmlDeclaration(   const char* _version,
00790                         const char* _encoding,
00791                         const char* _standalone );
00792 
00793     virtual ~TiPullXmlDeclaration() {}
00794 
00795     /// Version. Will return empty if none was found.
00796     const char * Version() const        { return version.c_str (); }
00797     /// Encoding. Will return empty if none was found.
00798     const char * Encoding() const       { return encoding.c_str (); }
00799     /// Is this a standalone document?
00800     const char * Standalone() const     { return standalone.c_str (); }
00801 
00802     // [internal use]
00803     virtual void Print( FILE* cfile, int depth ) const;
00804 
00805 protected:
00806     // used to be public
00807     #ifdef TIXML_USE_STL
00808         virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
00809     #endif
00810     virtual void StreamOut ( TIXML_OSTREAM * out) const;
00811     //  [internal use]
00812     //  Attribtue parsing starts: next char past '<'
00813     //                   returns: next char past '>'
00814 
00815     virtual bool Parse( ParsePosition in, const char* &out, bool throwaway );
00816 
00817 private:
00818     TIXML_STRING version;
00819     TIXML_STRING encoding;
00820     TIXML_STRING standalone;
00821 };
00822 
00823 
00824 /** Any tag that tinyXml doesn't recognize is saved as an
00825     unknown. It is a tag of text, but should not be modified.
00826     It will be written back to the XML, unchanged, when the file
00827     is saved.
00828 */
00829 class TiPullXmlUnknown : public TiPullXmlNode
00830 {
00831 public:
00832     TiPullXmlUnknown() : TiPullXmlNode( TiPullXmlNode::UNKNOWN ) {}
00833     virtual ~TiPullXmlUnknown() {}
00834 
00835     // [internal use]
00836     virtual void Print( FILE* cfile, int depth ) const;
00837 protected:
00838     #ifdef TIXML_USE_STL
00839         virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
00840     #endif
00841     virtual void StreamOut ( TIXML_OSTREAM * out ) const;
00842     /*  [internal use]
00843         Attribute parsing starts: First char of the text
00844                          returns: next char past '>'
00845     */
00846     virtual bool Parse( ParsePosition in, const char* &out, bool throwaway );
00847 };
00848 
00849 
00850 /** Always the top level node. A document binds together all the
00851     XML pieces. It can be saved, loaded, and printed to the screen.
00852     The 'value' of a document node is the xml file name.
00853 */
00854 class TiPullXmlDocument : public TiPullXmlNode
00855 {
00856     friend class TiPullXmlNode;
00857 public:
00858     /// Create an empty document, that has no name.
00859     TiPullXmlDocument();
00860     /// Create a document with a name. The name of the document is also the filename of the xml.
00861     TiPullXmlDocument( const char * documentName );
00862 
00863     #ifdef TIXML_USE_STL
00864     /// Constructor.
00865     TiPullXmlDocument( const std::string& documentName ) :
00866         TiPullXmlNode( TiPullXmlNode::DOCUMENT )
00867     {
00868         value = documentName;
00869         error = false;
00870     }
00871     #endif
00872 
00873     virtual ~TiPullXmlDocument() {}
00874 
00875     /** Load a file using the current document value.
00876         Returns true if successful. Will delete any existing
00877         document data before loading.
00878     */
00879     bool LoadFile();
00880     /// Save a file using the current document value. Returns true if successful.
00881     bool SaveFile() const;
00882     /// Load a file using the given filename. Returns true if successful.
00883     bool LoadFile( const char * filename );
00884     /// Save a file using the given filename. Returns true if successful.
00885     bool SaveFile( const char * filename ) const;
00886 
00887     #ifdef TIXML_USE_STL
00888     bool LoadFile( const std::string& filename )            ///< STL std::string version.
00889     {
00890         StringToBuffer f( filename );
00891         return ( f.buffer && LoadFile( f.buffer ));
00892     }
00893     bool SaveFile( const std::string& filename ) const      ///< STL std::string version.
00894     {
00895         StringToBuffer f( filename );
00896         return ( f.buffer && SaveFile( f.buffer ));
00897     }
00898     #endif
00899 
00900     /** Parse the given null terminated block of xml data.
00901     */
00902     virtual bool Parse( ParsePosition in, const char* &out, bool throwaway );
00903 
00904     /** Get the root element -- the only top level element -- of the document.
00905         In well formed XML, there should only be one. TinyXml is tolerant of
00906         multiple elements at the document level.
00907     */
00908     TiPullXmlElement* RootElement()         { return FirstChildElement(); }
00909 
00910     /** If an error occurs, Error will be set to true. Also,
00911         - The ErrorId() will contain the integer identifier of the error (not generally useful)
00912         - The ErrorDesc() method will return the name of the error. (very useful)
00913         - The ErrorRow() and ErrorCol() will return the location of the error (if known)
00914     */  
00915     bool Error() const                      { return error; }
00916 
00917     /// Contains a textual (english) description of the error if one occurs.
00918     const char * ErrorDesc() const  { return errorDesc.c_str (); }
00919 
00920     /** Generally, you probably want the error string ( ErrorDesc() ). But if you
00921         prefer the ErrorId, this function will fetch it.
00922     */
00923     const int ErrorId() const               { return errorId; }
00924 
00925     /** Returns the location (if known) of the error. The first column is column 1, 
00926         and the first row is row 1. A value of 0 means the row and column wasn't applicable
00927         (memory errors, for example, have no row/column) or the parser lost the error. (An
00928         error in the error reporting, in that case.)
00929 
00930         @sa SetTabSize, Row, Column
00931     */
00932     int ErrorRow() const;
00933     int ErrorCol() const;
00934 
00935     /** By calling this method, with a tab size
00936         greater than 0, the row and column of each node and attribute is stored
00937         when the file is loaded. Very useful for tracking the DOM back in to
00938         the source file.
00939 
00940         The tab size is required for calculating the location of nodes. If not
00941         set, the default of 4 is used. The tabsize is set per document. Setting
00942         the tabsize to 0 disables row/column tracking.
00943 
00944         Note that row and column tracking is not supported when using operator>>.
00945 
00946         The tab size needs to be enabled before the parse or load. Correct usage:
00947         @verbatim
00948         TiPullXmlDocument doc;
00949         doc.SetTabSize( 8 );
00950         doc.Load( "myfile.xml" );
00951         @endverbatim
00952 
00953         @sa Row, Column
00954     */
00955     void SetTabSize( int _tabsize )     { tabsize = _tabsize; }
00956 
00957     int TabSize() const { return tabsize; }
00958 
00959     /** If you have handled the error, it can be reset with this call. The error
00960         state is automatically cleared if you Parse a new XML block.
00961     */
00962     void ClearError()                       {   error = false; 
00963                                                 errorId = 0; 
00964                                                 errorDesc = ""; 
00965                                                 errorLocation.Clear(); 
00966                                                 //errorLocation.last = 0; 
00967                                             }
00968 
00969     /** Dump the document to standard out. */
00970     void Print() const                      { Print( stdout, 0 ); }
00971 
00972     // [internal use]
00973     virtual void Print( FILE* cfile, int depth = 0 ) const;
00974     // [internal use]
00975     void SetError( int err, const char* errorLocation, TiPullXmlParsingData* prevData );
00976 
00977     const char* getFileBuffer() const { return fileBuffer; }
00978     void setFileBuffer(const char* buf) { fileBuffer = buf; }
00979 
00980 protected :
00981     virtual void StreamOut ( TIXML_OSTREAM * out) const;
00982     #ifdef TIXML_USE_STL
00983         virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
00984     #endif
00985 
00986     void FindAllLineStarts( const char* p );
00987     int FindLine(TiPullXmlCursor location) const;
00988 
00989 private:
00990     bool error;
00991     int  errorId;
00992     TIXML_STRING errorDesc;
00993     int tabsize;
00994     TiPullXmlCursor errorLocation;
00995     std::deque<int> lineStarts;
00996     const char* fileBuffer;
00997 };
00998 
00999 
01000 /**
01001     A TiXmlHandle is a class that wraps a node pointer with null checks; this is
01002     an incredibly useful thing. Note that TiXmlHandle is not part of the TinyXml
01003     DOM structure. It is a separate utility class.
01004 
01005     Take an example:
01006     @verbatim
01007     <Document>
01008         <Element attributeA = "valueA">
01009             <Child attributeB = "value1" />
01010             <Child attributeB = "value2" />
01011         </Element>
01012     <Document>
01013     @endverbatim
01014 
01015     Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very 
01016     easy to write a *lot* of code that looks like:
01017 
01018     @verbatim
01019     TiXmlElement* root = document.FirstChildElement( "Document" );
01020     if ( root )
01021     {
01022         TiXmlElement* element = root->FirstChildElement( "Element" );
01023         if ( element )
01024         {
01025             TiXmlElement* child = element->FirstChildElement( "Child" );
01026             if ( child )
01027             {
01028                 TiXmlElement* child2 = child->NextSiblingElement( "Child" );
01029                 if ( child2 )
01030                 {
01031                     // Finally do something useful.
01032     @endverbatim
01033 
01034     And that doesn't even cover "else" cases. TiXmlHandle addresses the verbosity
01035     of such code. A TiXmlHandle checks for null pointers so it is perfectly safe 
01036     and correct to use:
01037 
01038     @verbatim
01039     TiXmlHandle docHandle( &document );
01040     TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).Element();
01041     if ( child2 )
01042     {
01043         // do something useful
01044     @endverbatim
01045 
01046     Which is MUCH more concise and useful.
01047 
01048     It is also safe to copy handles - internally they are nothing more than node pointers.
01049     @verbatim
01050     TiXmlHandle handleCopy = handle;
01051     @endverbatim
01052 
01053     What they should not be used for is iteration:
01054 
01055     @verbatim
01056     int i=0; 
01057     while ( true )
01058     {
01059         TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", i ).Element();
01060         if ( !child )
01061             break;
01062         // do something
01063         ++i;
01064     }
01065     @endverbatim
01066 
01067     It seems reasonable, but it is in fact two embedded while loops. The Child method is 
01068     a linear walk to find the element, so this code would iterate much more than it needs 
01069     to. Instead, prefer:
01070 
01071     @verbatim
01072     TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild( "Child" ).Element();
01073 
01074     for( child; child; child=child->NextSiblingElement() )
01075     {
01076         // do something
01077     }
01078     @endverbatim
01079 */
01080 class TiPullXmlHandle
01081 {
01082 public:
01083     /// Create a handle from any node (at any depth of the tree.) This can be a null pointer.
01084     TiPullXmlHandle( TiPullXmlNode* node )          { this->node = node; }
01085     /// Copy constructor
01086     TiPullXmlHandle( const TiPullXmlHandle& ref )   { this->node = ref.node; }
01087 
01088     /// Return a handle to the first child node.
01089     TiPullXmlHandle FirstChild() const;
01090     /// Return a handle to the first child node with the given name.
01091     TiPullXmlHandle FirstChild( const char * value, TiPullXmlNode::NodeType nType ) const;
01092     /// Return a handle to the first child element.
01093     TiPullXmlHandle FirstChildElement() const;
01094     /// Return a handle to the first child element with the given name.
01095     TiPullXmlHandle FirstChildElement( const char * value ) const;
01096 
01097     /** Return a handle to the "index" child with the given name. 
01098         The first child is 0, the second 1, etc.
01099     */
01100 //  TiPullXmlHandle Child( const char* value, int index ) const;
01101     /** Return a handle to the "index" child. 
01102         The first child is 0, the second 1, etc.
01103     */
01104     TiPullXmlHandle Child( int index ) const;
01105     /** Return a handle to the "index" child element with the given name. 
01106         The first child element is 0, the second 1, etc. Note that only TiPullXmlElements
01107         are indexed: other types are not counted.
01108     */
01109     TiPullXmlHandle ChildElement( const char* value, int index ) const;
01110     /** Return a handle to the "index" child element. 
01111         The first child element is 0, the second 1, etc. Note that only TiPullXmlElements
01112         are indexed: other types are not counted.
01113     */
01114     TiPullXmlHandle ChildElement( int index ) const;
01115 
01116     #ifdef TIXML_USE_STL
01117     TiPullXmlHandle FirstChild( const std::string& _value ) const           { return FirstChild( _value.c_str() ); }
01118     TiPullXmlHandle FirstChildElement( const std::string& _value ) const        { return FirstChildElement( _value.c_str() ); }
01119 
01120     TiPullXmlHandle Child( const std::string& _value, int index ) const         { return Child( _value.c_str(), index ); }
01121     TiPullXmlHandle ChildElement( const std::string& _value, int index ) const  { return ChildElement( _value.c_str(), index ); }
01122     #endif
01123 
01124     /// Return the handle as a TiPullXmlNode. This may return null.
01125     TiPullXmlNode* Node() const         { return node; } 
01126     /// Return the handle as a TiPullXmlElement. This may return null.
01127     TiPullXmlElement* Element() const   { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); }
01128     /// Return the handle as a TiPullXmlText. This may return null.
01129     TiPullXmlText* Text() const         { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); }
01130 
01131 private:
01132     TiPullXmlNode* node;
01133 };
01134 
01135 // typedefs back to the old interface class names
01136 typedef TiPullXmlDocument       TiXmlDocument;
01137 typedef TiPullXmlElement        TiXmlElement;
01138 typedef TiPullXmlComment        TiXmlComment;
01139 typedef TiPullXmlUnknown        TiXmlUnknown;
01140 typedef TiPullXmlAttribute      TiXmlAttribute;
01141 typedef TiPullXmlText           TiXmlText;
01142 typedef TiPullXmlDeclaration    TiXmlDeclaration;
01143 typedef TiPullXmlHandle         TiXmlHandle;
01144 
01145 
01146 
01147 #endif // TINYXML_INCLUDED
01148 

Generated on Mon Sep 12 19:58:57 2005 for Destiny3D by doxygen1.3-rc3